package com.huitone.gddw.utils;

import java.security.PrivateKey;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;

import org.apache.log4j.Logger;
import org.springframework.data.redis.core.StringRedisTemplate;

import com.alibaba.fastjson.JSONObject;

import cn.com.jit.csp.cypher.cipher.CertAuthClient;
import cn.com.jit.csp.cypher.result.AuthSignResult;
import cn.com.jit.csp.cypher.utils.KeyUtil;



public class CipherPTUtils {
	private final static Logger LOGGER = Logger.getLogger(CipherPTUtils.class);
	
	//初始化连接密码平台认证秘钥
	public static Map<String,String> authenticationCipher() {
		Map<String,String> resultMap =null;
		StringRedisTemplate stringRedisTemplate = SpringContextUtil.getBean("stringRedisTemplate");
		String IP = ContextPropertiesUtils.getProperty("ipAddress");
		String authCodeURI = ContextPropertiesUtils.getProperty("authCodeURI");
		String URL = IP+authCodeURI; 
		
		//获取授权码
		String json = HttpClientUtils.doPostByJson(URL,null,null);
		if(json != "") {
			JSONObject jsonObject = JSONObject.parseObject(json);
	        String code = jsonObject.getString("code");//状态码  0=成功   其他=失败
	        String message = jsonObject.getString("message");
	        if("0".equals(code)) {
	        	Object data = jsonObject.getString("data");
	 	        JSONObject authCodeJsonObject = JSONObject.parseObject(data.toString());
	 	        String authCode = authCodeJsonObject.getString("authCode");//authCode	String	授权码
	        	//应用身份认认，授权码签名
	        	String signature = "";
	        	String signAlgorithm="";
	        	
	        	try {
	    			String sm2PrivateKeyBase64 = ContextPropertiesUtils.getProperty("sm2PrivateKeyBase64").toString();
	    			PrivateKey sm2PrivateKey= KeyUtil.SM2KeyBase64ConvertPirvateKey(sm2PrivateKeyBase64);//私钥的base64值
	    			AuthSignResult sm2AuthSignResult2= (AuthSignResult) CertAuthClient.keyAuthCodeSign(sm2PrivateKey,authCode);
	    			 signature = sm2AuthSignResult2.getSignature();
	    			 signAlgorithm = sm2AuthSignResult2.getSignAlgorithm();
	    			 LOGGER.info("授权码签名成功   ,签名值:"+signature+"    签名算法:"+signAlgorithm);
	    		} catch (Exception e) {
	    			LOGGER.info("授权码签名失败 ");
	    		}
	        	
				
	        	//应用身份认证 请求参数
	        	Map<String, Object> map = new HashMap<String, Object>();
	    		map.put("code", ContextPropertiesUtils.getProperty("appName"));//code	String	是	应用标识
	    		map.put("authCode", authCode);//authCode	String	是	授权码
	    		map.put("signature", signature);//signature	String	否	签名值)
	    		map.put("signAlgorithm", signAlgorithm);//signAlgorithm	String	否	签名算法     		SHA1withRSAEncryption
	    		
	    		String jsonString = JSONObject.toJSONString(map);
	    		//应用身份认证
	    		String authenticationURI = ContextPropertiesUtils.getProperty("authenticationURI");
	    		String authURL = IP+authenticationURI; 
	        	String jsonAuthenticationResult = HttpClientUtils.doPostByJson(authURL,jsonString,null);
	        	if(jsonAuthenticationResult != "") {
	        		JSONObject jsonAuthentication = JSONObject.parseObject(jsonAuthenticationResult);
	            	//响应报文参数
	            	String codeAuthe =jsonAuthentication.getString("code");//code	String	状态码            	0=成功            			其他=失败
	            	String messageAuthe =jsonAuthentication.getString("message");//message	String	描述信息
	            	Object dataAuthe =jsonAuthentication.getString("data");//data	object	结果信息
	            	if("0".equals(codeAuthe)) {
	            		JSONObject AuthentiDateToken = JSONObject.parseObject(dataAuthe.toString());
	            		String token =AuthentiDateToken.getString("token");//token	String	Token值
	            		String expirationTime =AuthentiDateToken.getString("expirationTime");//expirationTime	String	Token失效时间
	            		
	            		stringRedisTemplate = SpringContextUtil.getBean("stringRedisTemplate");
	            		//token添加之前先做删除
	            		stringRedisTemplate.delete("token");
	            		stringRedisTemplate.opsForHash().put("token", token, expirationTime);
	            		resultMap=new HashMap<>();
	            		resultMap.put(token, expirationTime);
	            		LOGGER.info("应用身份认证  保存token到redis成功     ");
	            		return resultMap;
	            		
	            	}else {
	            		LOGGER.error("  应用身份认证失败： 响应状态码是,,resultjson="+jsonAuthenticationResult+"     code=" +codeAuthe+",URL是 "+URL);
	            	}
	        	}else {
	        		LOGGER.error("应用身份认证没有响应报文参：  ,  应用身份认证失败 URL是 "+URL);
	        	}
	        }else {
	        	LOGGER.error(" 获取授权码失败 ：响应状态码   , 连接到密码平台失败 URL是 "+URL);
	        }
		}else {
			LOGGER.error(" 调用获取授权码接口没有响应报文参数 ,：  , 连接到密码平台失败 ,URL是 "+URL);
			
		}
			return resultMap;
	}
		
	
	//请求密码平台接口解密 登陆密码
	public static String decryptText(String text,String token,String keyCode) {
		String IP = ContextPropertiesUtils.getProperty("ipAddress");
		String textDecryptURI = ContextPropertiesUtils.getProperty("textDecryptURI");
		String URL = IP+textDecryptURI;
		
		//请求参数
    	Map<String, Object> map = new HashMap<String, Object>();
		map.put("keyCode", keyCode);//密钥标识   
		map.put("algorithmParam", "SM2");//算法参数
		map.put("encData",text);//加密密文，格式同文本数据加密接口
		
		String jsonString = JSONObject.toJSONString(map);
    	String decryptResult = HttpClientUtils.doPostByJson(URL,jsonString,token);
    	LOGGER.info("解密接口 返回数据 ==  "+ decryptResult);
    	LOGGER.info("解密文本     "+ text);
    	LOGGER.info("请求参数     "+ jsonString);
    	
    	if(decryptResult != "") {
    		JSONObject decrypObj = JSONObject.parseObject(decryptResult);
        	//响应报文参数
        	String code =decrypObj.getString("code");//code	String	状态码            	0=成功            			其他=失败
        	if("0".equals(code)) {
        		String message =decrypObj.getString("message");//message	String	描述信息
            	String data =decrypObj.getString("data").toString();//data	object	结果信息
            	JSONObject dataObj = JSONObject.parseObject(data);
            	String passWord =dataObj.getString("data");
            	
            	LOGGER.info("解密成功， 接口返回数据 ,状态码==  "+ code+"   描述信息:"+message+"   结果信息:data = "+passWord);
            	return passWord;
        	}else {
        		LOGGER.error("解密失败,,状态码 ,"+code);
        	}
    	}else {
    		LOGGER.error("调用解密接口失败,,没有响应报文参数 ,");
    	}
		return null;
	}
	
	
	//创建非对称密,此接口返回密码标识
	public static String createKey(String token) {
		String keyCode = null;
		String IP = ContextPropertiesUtils.getProperty("ipAddress");
		String textDecryptURI = ContextPropertiesUtils.getProperty("createKeyPair");
		String URL = IP+textDecryptURI; 
		//请求参数
    	Map<String, Object> map = new HashMap<String, Object>();
		map.put("algorithm", "SM2");//密钥算法	
		map.put("length", 256);//length	number	是	密钥长度	SM2长度：256
		map.put("period",365*1000);//有效期 单位天
		map.put("keyUsages","0");//0=加解密
		
		String jsonString = JSONObject.toJSONString(map);
		String createKeyResult = HttpClientUtils.doPostByJson(URL, jsonString, token);
		JSONObject jsonObject = JSONObject.parseObject(createKeyResult);
		String message = jsonObject.getString("message");
        String code = jsonObject.getString("code");//0=成功
        Object objKeyCode = jsonObject.getString("data");
        
        if("0".equals(code)) {
        	 JSONObject jsonObject2 = JSONObject.parseObject(objKeyCode.toString());
        	 keyCode = jsonObject2.getString("keyCode");
        	 String expirationTime = jsonObject2.getString("expirationTime");
        	 StringRedisTemplate stringRedisTemplate = SpringContextUtil.getBean("stringRedisTemplate");
        	 stringRedisTemplate.delete("MMPTkeyCode");
     		 stringRedisTemplate.opsForHash().put("MMPTkeyCode", keyCode, expirationTime);
     		 LOGGER.info("redis保存keyCode 成功 ");
        }else {
        	 LOGGER.info("创建非对称密接口失败jsonObject== "+jsonObject+"    , 返回状态码code== "+code+"   ,message=="+message+"");
        }
		return keyCode;
	}
	
	//获取公钥 ,通过非对称密钥创建接口返回的keyCode密钥标识 获取公钥
	public static String getKeyPair() {
	//获取tonken ,调用接口需要token
		StringRedisTemplate stringRedisTemplate = SpringContextUtil.getBean("stringRedisTemplate");
		
		
		//从redis获取非对称秘钥 判断是否过期
    	Map<Object, Object> MMPTkeyCode = stringRedisTemplate.opsForHash().entries("MMPTkeyCode");
    	if(MMPTkeyCode.size() >0){
    		LOGGER.info("   redis存在秘钥标识 ,    需要判断秘钥标识过期时间");
    		Iterator<Entry<Object, Object>> iterator = MMPTkeyCode.entrySet().iterator();
        	Entry<Object, Object> entry = iterator.next();
        	String keyCode = entry.getKey().toString();
        	String expirationTime = entry.getValue().toString();
        	SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        	try {
				Date expirationDate = sdf.parse(expirationTime);
				long currentTimeMillis = System.currentTimeMillis();
				Date currentDate = new Date(currentTimeMillis);
				boolean before = expirationDate.before(currentDate);//过期时间在当前时间前面, 表示过期了       true过期       fasle不过期
				if(before==false) {
					LOGGER.info("redis非对称秘钥标识   不过期,  过期时间为expirationTime== "+expirationTime);
					return keyCode;
				}else {
					LOGGER.info(" redis的非对称秘钥标识 ,   已过期  ,过期时间为expirationTime== "+expirationTime);
				}
			} catch (ParseException e) {
				LOGGER.info("时间转换异常     "+e.getMessage());
			}
    	}
    	
		
    	Map<Object, Object> mapTonken = stringRedisTemplate.opsForHash().entries("token");
    	Iterator<Entry<Object, Object>> iterator = mapTonken.entrySet().iterator();
    	Entry<Object, Object> entry = iterator.next();
    	String token = entry.getKey().toString();  //token
//	     String expirationTime = entry.getValue().toString();  token 过期时间
		
//    	LOGGER.error("test  206行    获取公钥接口 ");
    	
//    	非对称密钥创建,  返回keyCode密钥标识
		String keyCode = createKey(token);
		if(keyCode == null) {
			LOGGER.error("非对称密钥创建接口失败,keyCode密钥标识  null");
			return null;
		}
		
		String IP = ContextPropertiesUtils.getProperty("ipAddress");
		String textDecryptURI = ContextPropertiesUtils.getProperty("getPublicKey");
		String URL = IP+textDecryptURI; 
		
		
		//请求参数
    	Map<String, Object> map = new HashMap<String, Object>();
		map.put("keyCode", keyCode);
		
		String jsonString = JSONObject.toJSONString(map);
		String createKeyResult = HttpClientUtils.doPostByJson(URL, jsonString, token);
		JSONObject jsonObject = JSONObject.parseObject(createKeyResult);
		
		 String message = jsonObject.getString("message");
         String code = jsonObject.getString("code");//0=成功
         Object obj = jsonObject.getString("data");
         if("0".equals(code)) {
        	 JSONObject jsonObject2 = JSONObject.parseObject(obj.toString());
        	 String publicKey = jsonObject2.getString("publicKey");//公钥明文[BASE64]
        	 
        	 //publicKey存到redis
        	 stringRedisTemplate.delete("MMPTpublicKey");
     		 stringRedisTemplate.opsForHash().put("MMPTpublicKey", publicKey,"");
     		LOGGER.info(" 保存建MMPTpublicKey  公钥保存到 redis成功 =="+publicKey);
        	 return publicKey;
         }else {
        	 LOGGER.error("获取公钥失败,code=="+code+"  ,message=="+message);
         }
         
    	return null;
	}
	
	
	
}





